<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
<script>
	/**
	 * 将扁平数组转换为树形结构
	 * @param {Array} arr - 扁平结构数组，每个元素必须包含id和pid属性
	 *        id 表示当前节点唯一标识，pid 表示父节点标识
	 * @returns {Array} 树形结构数组，每个节点包含children属性存储子节点
	 */
	function arrayToTree(arr){
		// 创建id到节点的映射表，初始化children结构
		const map = {}
		// 存储顶层节点（根节点）的容器
		const tree = []
		
		// 第一轮循环：建立节点映射表
		for(let item of arr){
			// 创建新节点对象，保留原属性并初始化空children数组
			map[item.id] = {...item,children:[]}
		}
		
		// 第二轮循环：构建节点层级关系
		for(let item of arr){
			if (!item.pid){
				// 当前节点无父节点，作为根节点放入tree
				tree.push(map[item.id])
			} else {
				// 当前节点有父节点，将其加入父节点的children数组
				map[item.pid].children.push(map[item.id])
			}
		}
		
		return tree
	}

    const arr = [
        {id:1,pid:null},
        {id: 2,pid: 1},
        {id: 3,pid: 2},
        {id: 4,pid: 3}
    ]
    console.log(arrayToTree(arr))
</script>
</html>